package sessions

import (
	"gitee.com/sdynasty/clever/socket"
	"sync"
)

type SessionMgr struct {
	isWebSocket bool
	sessions sync.Map	// fd - session
	bindUidMap sync.Map	// uid - fd
	bindAccountMap sync.Map	// account - fd
}

var static_sessionMgr *SessionMgr

func GetSessionMgr() *SessionMgr {
	return static_sessionMgr
}

func NewSessionMgr() *SessionMgr {
	static_sessionMgr = &SessionMgr{}
	return static_sessionMgr
}

func (sm *SessionMgr) GetSessionByFd(id uint32) *Session {
	temp, exit := sm.sessions.Load(id)
	if exit {
		if sess, ok := temp.(*Session); ok {
			return sess
		}
	}
	return nil
}

// 获取Session by uid
func (sm *SessionMgr) GetSessionByUid(uid int32) (sess *Session) {
	var fd uint32
	var ok bool
	fdTemp, exit := sm.bindUidMap.Load(uid)
	if exit {
		if fd, ok = fdTemp.(uint32); !ok {
			return
		}

		temp, exit := sm.sessions.Load(fd)
		if exit {
			sess, ok = temp.(*Session)
		}
	}

	return
}

// 获取Session by account
func (sm *SessionMgr) GetSessionByAccount(acc string) (sess *Session) {
	var fd uint32
	var ok bool
	fdTemp, exit := sm.bindAccountMap.Load(acc)
	if exit {
		if fd, ok = fdTemp.(uint32); !ok {
			return
		}

		temp, exit := sm.sessions.Load(fd)
		if exit {
			sess, ok = temp.(*Session)
		}
	}

	return
}

// 绑定Session 生成 account map
func (sm *SessionMgr) BindSessionAccount(sess *Session, account string) {
	sm.bindAccountMap.Store(account, sess.Fd)

	sess.setAccount(account)
}

// 绑定Session 生成 uid map
func (sm *SessionMgr) BindSessionUid(sess *Session, uid int32) {
	sm.bindUidMap.Store(uid, sess.Fd)

	sess.setUid(uid)
}

// 绑定Session
func (sm *SessionMgr) BindSession(sess *Session, uid int32) {
	sm.bindUidMap.Store(uid, sess.Fd)

	sess.setUserData(uid, "")
}

// 添加web socket session
func (sm *SessionMgr) SetSessionWithWS(fd uint32, conn *socket.ConnectionWs) {
	sess := NewSessionWithWS(fd, conn)
	sm.sessions.Store(fd, sess)
}

// 添加tpc socket session
func (sm *SessionMgr) SetSessionWithTCP(fd uint32, conn *socket.ConnectionNet) {
	sess := NewSessionWithTCP(fd, conn)
	sm.sessions.Store(fd, sess)
}

// 删除Session Object
func (sm *SessionMgr) DeleteSessionObject(sess *Session) {
	sm.sessions.Delete(sess.Fd)
	sm.bindUidMap.Delete(sess.userData.Uid)
	sm.bindAccountMap.Delete(sess.userData.Account)
}

// 删除Session
func (sm *SessionMgr) DeleteSession(fd uint32, uid int32, account string) {
	sm.sessions.Delete(fd)
	sm.bindUidMap.Delete(uid)
	sm.bindAccountMap.Delete(account)
}


func (sm *SessionMgr) IsFdUsed(fd uint32) bool {
	_, exit := sm.sessions.Load(fd)
	return exit
}

func (sm *SessionMgr) GetAllSession() [] *Session {
	list := make([]*Session, 0)
	sm.sessions.Range(func(k, v interface{}) bool {
		list = append(list, v.(*Session))
		return true
	})
	return list
}